package study.JavaAdvanced;

import com.sun.source.tree.Tree;

import java.util.*;

/**
 * date:2025.10.23
 * title:HashSet
 * author:fzy
 */
    /*
    set集合：不允许重复元素，没有索引，不支持for循环
     */

/**
 * set不保证便利顺序
 */
//hashSet是基于hashMap实现，
//特点：不允许重复，允许null，无序线程不安全

    /*
    哈希值：是jdk根据对象的地址，字符串，数字算出来的int数值
    哈希值不是地址
     */
public class Java_4 {
    public static void main(String[] art) {
//        setTest.test();
//        setTest.getHash();
//        setTest.hashSetDemo();
//        student a = new student("111", 123);
//        student a1 = new student("222", 221);
//        student a2 = new student("333", 12);
//        student a3 = new student("444", 12);
//        student a4 = new student("333", 12);
//        student a5 = new student("333", 12);
//        StudentManager_hashset studentManagerHashset = new StudentManager_hashset();
//        studentManagerHashset.add(a);
//        studentManagerHashset.add(a1);
//        studentManagerHashset.add(a2);
//        studentManagerHashset.print();
//        SetDemo.ListHashSetDemo();
//        SetDemo.TreeSetDemo();
//        StudentManager_TreeSet studentManagerTreeSet = new StudentManager_TreeSet();
//
//        studentManagerTreeSet.add(a);
//        studentManagerTreeSet.add(a1);
//        studentManagerTreeSet.add(a2);
//        studentManagerTreeSet.add(a3);
//        studentManagerTreeSet.add(a4);
//        studentManagerTreeSet.add(a5);
//        studentManagerTreeSet.print();
        StudentIns_TreeSet stu1 = new StudentIns_TreeSet("小1",100,"20202011");
        StudentIns_TreeSet stu2 = new StudentIns_TreeSet("小2",123,"20202021");
        StudentIns_TreeSet stu3 = new StudentIns_TreeSet("小3",111,"20202031");
        StudentIns_TreeSet stu4 = new StudentIns_TreeSet("小4",23,"20202042");
        StudentIns_TreeSet stu5 = new StudentIns_TreeSet("小5",13,"20202011");
        StudentIns_TreeSet stu6 = new StudentIns_TreeSet("小1",123,"20202051");
        StudentGradesManager studentGradesManager = new StudentGradesManager();
        studentGradesManager.add(stu1);
        studentGradesManager.add(stu2);
        studentGradesManager.add(stu3);
        studentGradesManager.add(stu4);
        studentGradesManager.add(stu5);
        studentGradesManager.add(stu6);
        studentGradesManager.print();
        TreeSet<Integer> inA  = randomClass.getRandom();
        for(int i:inA){
            System.out.println(i);
        }

    }
}

class setTest {
    static void test() {
        Set<String> set = new HashSet<>();
        set.add("111");
        set.add("222");
        set.add("333");
        set.add("222");
        set.add("重地");
        set.add("通话");
        System.out.println(set);
    }

    static void getHash() {
        student stu = new student("fff", 123);
        student stu2 = new student("fff", 123);
        int hashcodeInt = stu.hashCode();
        int hashcodeInt2 = stu.hashCode();
        //同一个对象多次调用hashCode返回的值相同
        //默认情况下，不同对象哈希值不同
        System.out.println(hashcodeInt);
        System.out.println(hashcodeInt2);
        System.out.println(stu2.hashCode());
        System.out.println("重地".hashCode());
        System.out.println("通话".hashCode());
    }

    static void hashSetDemo() {
        Set<String> set = new HashSet<>();
        set.add("111");
        set.add("222");
        set.add("333");
        for (String s : set) {
            System.out.println(s);
        }
    }
}

class HashTestClass {
    private HashSet<Integer> hashSet = new HashSet<Integer>();

    //HashSet不允许有重复元素，所以在重复添加一个元素的时候这个元素只会出现一次
    public boolean addToHashSet(int a) {
        return hashSet.add(a);
    }

    //判断是否含有某个元素
    public boolean isContain(int param) {
        //自动装箱
        return hashSet.contains(param);
    }

    //删除某个元素
    public boolean deleteHashSet(int a) {
        return hashSet.remove(a);
    }

    //清空hashset
    public void clearHashSet() {
        hashSet.clear();
    }

    public int getSize() {
        return hashSet.size();
    }
}
/*
哈希表存储
哈希表长度为16 所以是0~15
将存储元素的哈希值%16 存储到对应1-15的链表数组，
在存储是先对比哈希值在对比数值，唯一就添加到链表末尾
 */

//案例
//这里需要重写学生类的equal方法，便于后续hashset的数值对比
class StudentManager_hashset {
    private HashSet<student> db = new HashSet<>();

    void add(student stu) {
        db.add(stu);
    }

    void print() {
        for (student stu : db) {
            System.out.println(stu.name + "," + stu.age);
        }
    }
}

class SetDemo {
    /*
LinkedHashSet
哈希表和链表实现set接口，具有可以预测的迭代次序
由链表保证元素有序
由哈希表保证元素唯一
 */
    static void ListHashSetDemo() {
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("hello");
        linkedHashSet.add("world");
        linkedHashSet.add("333");
        for (String s : linkedHashSet) {
            System.out.println(s);
        }
    }

    /*
    TreeSet集合
        元素有序：不是存储取出有序，而是按照一点的规则排序
        TreeSet():自然排序,1~9,a~Z:注意存储的对象必须实现自然排序接口
        TreeSet(Comparator comparator):根据指定的规则排序
    没有带索引的方法
    没有重复元素
     */
    static void TreeSetDemo() {
        TreeSet<Integer> treeSet = new TreeSet<>();
        treeSet.add(123);
        treeSet.add(12);
        treeSet.add(332);
        treeSet.add(90);
        treeSet.add(90);
        for (Integer i : treeSet) {
            System.out.println(i);
        }
    }
}

//案例，使用Treeset存储学生
//这里存储的student必须实现comparaTo接口
/*
 @Override
 //返回值为正数，就按照升序排，
 返回值为负数，就按照降序拍
 0不添加
    public int compareTo(student o) {
    int num = this.age - o .age
        return num;
    }
 */
class StudentManager_TreeSet {
    private TreeSet<student> db = new TreeSet<>();
    //比较器规则和comparable一样的
    private TreeSet<student> db2 = new TreeSet<>(new Comparator<student>() {
        @Override
        public int compare(student o1, student o2) {
            if (o1.age == o2.age && o1.name != o2.name) {
                return 1;
            }
            return o1.age - o2.age;
        }
    });


    void add(student stu) {
        db.add(stu);
        db2.add(stu);
    }

    void print() {
        for (student s : db2) {
            System.out.println(s.name + "," + s.age);
        }
    }

}

//案例按照成绩排序

class StudentIns_TreeSet implements Comparable<StudentIns_TreeSet>{
    private String name;
    private Integer Grades;
    private String Id;

    public StudentIns_TreeSet(String name, Integer grades, String id) {
        this.name = name;
        Grades = grades;
        Id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getGrades() {
        return Grades;
    }

    public void setGrades(Integer grades) {
        Grades = grades;
    }

    public String getId() {
        return Id;
    }

    public void setId(String id) {
        Id = id;
    }

    @Override
    public int compareTo(StudentIns_TreeSet o) {
        if (!this.getId().equals(o.getId())) {
            return this.getGrades() - o.getGrades();
        }
        return 0;
    }
}

class StudentGradesManager {
    //由比较器构造方式
    private TreeSet<StudentIns_TreeSet> grades_db = new TreeSet<>(new Comparator_grades());
    //无参构造方式
    private TreeSet<StudentIns_TreeSet> grades_db2 = new TreeSet<>();
    class Comparator_grades implements Comparator<StudentIns_TreeSet> {
        @Override
        public int compare(StudentIns_TreeSet o1, StudentIns_TreeSet o2) {
            if (!o1.getId().equals(o2.getId())) {
                return o1.getGrades() - o2.getGrades();
            }
            return 0;
        }
    }

    void add(StudentIns_TreeSet stu) {
        grades_db.add(stu);
        grades_db2.add(stu);
    }

    void print() {
        for (StudentIns_TreeSet stu : grades_db2) {
            System.out.println(stu.getName() + "学号为:" + stu.getId() + ",成绩为:" + stu.getGrades());
        }
    }
}

//案例不重复的带顺序的随机数
class randomClass{
    static TreeSet<Integer> getRandom(){
        TreeSet<Integer> randomArray = new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        for(int i = 0;i<100;i++){
            double param = Math.random()*100;
            int num = Math.toIntExact(Math.round(param));
            randomArray.add(num);
        }
        return randomArray;
    }
}

